package shovelsoft.btmetaparser.tokens;

import java.io.InputStream;

/***
 * Data is a token representing raw data, usually a UTF-8 string.
 * @author cds
 */
public class Data implements IToken {

	public final byte[] mData;
	
	/***
	 * Read raw data from the input stream.
	 * @param head byte of data already read from the input stream (both signaling a Data type, and making up part of the Data header).
	 * @param tail the rest of the input stream
	 * @throws Exception
	 */
	public Data(int head, InputStream tail) throws Exception {
		
		byte[] d;
		
		if(head < '0' || head > '9')
			throw new Exception("unexpected token" + head);
		
		StringBuilder sb = new StringBuilder();
		for(;;) {
			sb.append((char)head);
			head = tail.read();
			
			if(head<'0' || head>'9')
				break;
		}
		if(head != ':')
			throw new Exception("unexpected token" + head);
		
		long length = Long.parseLong( sb.toString() );
		
		d = new byte[ (int)length ];
		
		if(tail.read(d) != length)
			throw new Exception("error reading data");
		
		mData = d;
	}
	
	public Data(byte[] data) {
		
		mData = data;
	}

	/***
	 * Accept a visit from a token parser (double dispatch)
	 * @param tp Token Parser
	 */
	@Override
	public void accept(ITokenParser tp) throws Exception {
		
		tp.visit(this);
	}
	
	@Override
	public boolean equals(Object o) {
		
		if(!(o instanceof Data))
			return false;
		
		Data d = (Data)o;
		
		if(d.mData.length != mData.length)
			return false;
		
		for(int i=0;i<mData.length; ++i)
			if(mData[i] != d.mData[i])
				return false;
		
		return true;
	}
	
	@Override
	public int hashCode() {
		
		return mData.hashCode();
	}
	
	@Override
	public String toString() {
		
		byte[] d = mData;
		if(d.length > 8) {
			d = new byte[8];
			for(int i=0;i<8;++i)
				d[i] = mData[i];
		}
		return "DATA \"" + new String(d) + "\"";
	}
}


